home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / hardware / md.1 < prev    next >
Text File  |  1989-02-17  |  27KB  |  571 lines

  1. Path: xanth!ames!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i021:  md - memory diagnostic
  5. Message-ID: <11760@swan.ulowell.edu>
  6. Date: 17 Feb 89 01:23:05 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 560
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: jc3b21!fgd3@uunet.UU.NET (Fabbian G. Dufoe)
  12. Posting-number: Volume 89, Issue 21
  13. Archive-name: hardware/md.1
  14.  
  15. [uuencode executable included.  ..Bob]
  16.  
  17. #    This is a shell archive.
  18. #    Remove everything above and including the cut line.
  19. #    Then run the rest of the file through sh.
  20. #----cut here-----cut here-----cut here-----cut here----#
  21. #!/bin/sh
  22. # shar:    Shell Archiver
  23. #    Run the following text with /bin/sh to create:
  24. #    ReadMe
  25. #    Makefile
  26. #    MD.c
  27. #    MD.doc
  28. #    MD.uue
  29. # This archive created: Thu Feb 16 20:20:53 1989
  30. cat << \SHAR_EOF > ReadMe
  31.      This archive contains the source, documentation, and executable for a
  32. public domain memory diagnostic program.  When you unpack the archive you
  33. should have the following files:
  34.  
  35.      ReadMe--This file.
  36.      MD--The executable program (may be packed as MD.uue, requiring you to
  37.          run "uudecode").
  38.      MD.doc--The documentation file explaining how MD works and how to use
  39.              it.
  40.      Makefile--Input for the Lattice LMK program to create MD from the
  41.                source.
  42.      MD.c--The source code for MD.
  43.      MD.uue--The executable program in uuencoded form.  To create the
  44.              executable run "uudecode MD.uue".
  45.  
  46.      MD will run with any Amiga configuration but requires a stack size of
  47. 10000.  It does not take over the machine but it does soak up any available
  48. memory while it is running.  It takes about 8 minutes to test a 2.5MB
  49. machine.
  50. SHAR_EOF
  51. cat << \SHAR_EOF > Makefile
  52. # Compile and link MD
  53.  
  54. MD: MD.o
  55.    blink FROM LIB:c.o+MD.o TO MD LIB LIB:lc.lib+LIB:amiga.lib NODEBUG SMALLCODE SMALLDATA MAP ram:MD.map
  56.  
  57. MD.o: MD.c
  58.    lc MD
  59. SHAR_EOF
  60. cat << \SHAR_EOF > MD.c
  61. /* MD.c
  62.  
  63.    by Fabbian G. Dufoe, III
  64.  
  65.    This is a public domain program.  Use it however you like.
  66.  
  67.    This program tests any memory which the operating system will allocate to
  68.    it.  It tests the memory one byte at a time by setting it to 0x00, the
  69.    comparing it to 0x00, setting it to 0xff, and comparing it to 0xff.  If
  70.    the comparison fails it writes the memory address (the pointer value),
  71.    the expected contents, and the actual contents of the memory location to
  72.    standard output.  Standard output may be redirected to a file if it is
  73.    desired to save the report.
  74.  
  75. */
  76.  
  77. #define NULL 0L
  78. #define SIZE 1000
  79. #define VERSION "Version 1.0, 10 January 1989\n\n"
  80.  
  81. #include <time.h>
  82. #include <stdio.h>
  83.  
  84. typedef struct
  85. {
  86.    unsigned char *ptr;
  87.    unsigned long int size;
  88. } Block;
  89.  
  90. void
  91. main()
  92. {
  93.    Block block[SIZE];
  94.    unsigned short int count = 0;
  95.    unsigned long int errct = 0;
  96.    unsigned short int high;
  97.    unsigned long int offset;
  98.    unsigned char *ptr;
  99.    unsigned long int size;
  100.    signed long int t;
  101.    static unsigned char TestVal[] = {0, 0xff, 0x55, 0xaa};
  102.    unsigned short int val;
  103.  
  104.    /* We want to include the time the diagnostic program was run in the
  105.       report.  That requires getting the current system time.
  106.    */
  107.    time(&t);
  108.  
  109.    /* We'll print a report heading and copyright notice at the beginning.
  110.    */
  111.    printf("MD--Memory Diagnostic.\n");
  112.    printf("by Fabbian G. Dufoe, III\n");
  113.    printf(VERSION);
  114.    printf("Memory tested %s\n\n", ctime(&t));
  115.  
  116.    /* We'll start by allocating memory in blocks of one megabyte.  The plan
  117.       is to allocate as many one-megabyte blocks as we can.  Then we'll
  118.       halve the block size, allocate as many blocks of that size as we can,
  119.       and repeat the process until (a) all the memory is gone or (b) we've
  120.       filled the array we allocated for keeping track of memory blocks.
  121.    */
  122.    size = 1048576;
  123.    while (size > 0 && count < SIZE)
  124.    {
  125.       fprintf(stderr, "Allocating %ld byte blocks.\n", size);
  126.       while ((ptr = (unsigned char *)malloc(size)) != NULL)
  127.       {
  128.          block[count].ptr = ptr;
  129.          block[count++].size = size;
  130.       }
  131.       if (size == 1)
  132.          size = 0;
  133.       else
  134.          size >>= 1;
  135.    }
  136.  
  137.    /* Because we expect to seldom use the entire array we've set aside we
  138.       need to save the number of the highest element actually used.
  139.    */
  140.    high = count;
  141.  
  142.    /* At this point we want to sort the block pointers.  It makes the output
  143.       easier to follow if memory errors are reported in ascending order
  144.       by their address.  We aren't guaranteed that memory will be
  145.       allocated in any particular order.  We'll use an insertion sort and
  146.       we'll sort only that part of the array we used.  That means we'll
  147.       keep the index values between 0 and high.
  148.  
  149.       An insertion sort works by shifting all the items left of the current
  150.       one right one position until an item is less than the current one.
  151.       Imagine the items to be sorted are laid out from left to right.  Then
  152.       the sort places the current item in the position vacated by the last
  153.       item to be shifted right.  The sort starts with the second item as
  154.       the current one and proceeds to the right until all the items have had
  155.       a turn as the current one.
  156.    */
  157.    fprintf(stderr, "Sorting block list.\n");
  158.    for (count = 1; count < high; count++)
  159.    {
  160.       short int i;
  161.  
  162.       ptr = block[count].ptr;
  163.       size = block[count].size;
  164.       i = count - 1;
  165.       while (i >=0 && ptr < block[i].ptr)
  166.       {
  167.          block[i+1].ptr = block[i].ptr;
  168.          block[i+1].size = block[i].size;
  169.          i--;
  170.       }
  171.       block[i+1].ptr = ptr;
  172.       block[i+1].size = size;
  173.    }
  174.    fprintf(stderr, "Sort complete.\n");
  175.  
  176.    /* We'll list the block addresses and size in the report.
  177.    */
  178.    printf("Blocks examined:\n");
  179.    printf("Block #    Address         Size\n\n");
  180.    for (count = 0; count < high; count++)
  181.    {
  182.       printf("%4d      %8lX      %7ld\n", count, block[count].ptr,
  183.              block[count].size);
  184.    }
  185.    printf("\n");
  186.  
  187.    /* Now that we've sorted our list of blocks we're ready to start testing
  188.       them.  The first step is to initialize all the variables to 0, the
  189.       first test value.
  190.    */
  191.    for (count = 0; count < high; count++)
  192.    {
  193.       fprintf(stderr, "Initializing block %d, %ld bytes.\n", count,
  194.                       block[count].size);
  195.       for (offset = 0; offset < block[count].size; offset++)
  196.          *(block[count].ptr+offset) = TestVal[0];
  197.    }
  198.  
  199.    /* Next we'll go through all the blocks to see if they contain the test
  200.       value with which they were loaded.  If not we'll identify the address
  201.       that failed, the value it contained, and the value it should have
  202.       contained.  We'll do that for each valid test value.
  203.    */
  204.    for (val = 1; val < 4; val++)
  205.    {
  206.       fprintf(stderr, "Testing value %X.\n", TestVal[val-1]);
  207.       for (count = 0; count < high; count++)
  208.       {
  209.          fprintf(stderr, "Testing block %d, %ld bytes with %X\n", count,
  210.                          block[count].size, TestVal[val-1]);
  211.          for (offset = 0; offset < block[count].size; offset++)
  212.          {
  213.             if (*(block[count].ptr+offset) != TestVal[val-1])
  214.             {
  215.                printf("ERROR! Address: %8lX  found: %2X  expected: %2X\n",
  216.                        block[count].ptr+offset, *(block[count].ptr+offset),
  217.                        TestVal[val-1]);
  218.                errct++;
  219.             }
  220.             *(block[count].ptr+offset) = TestVal[val];
  221.          }
  222.       }
  223.    }
  224.  
  225.    /* We've tested for all values except the last one.  It's time to do that
  226.       now.
  227.    */
  228.    val--;
  229.    fprintf(stderr, "Testing value %X.\n", TestVal[val]);
  230.    for (count = 0; count < high; count++)
  231.    {
  232.       fprintf(stderr, "Testing block %d, %ld bytes with %X\n", count,
  233.               block[count].size, TestVal[val]);
  234.       for (offset = 0; offset < block[count].size; offset++)
  235.       {
  236.          if (*(block[count].ptr+offset) != TestVal[val])
  237.          {
  238.             printf("ERROR! Address: %8lX  found: %2X  expected: %2X\n",
  239.                     block[count].ptr+offset, *(block[count].ptr+offset),
  240.                     TestVal[val]);
  241.             errct++;
  242.          }
  243.       }
  244.    }
  245.  
  246.    /* The testing is finished so we'll report the number of errors we found.
  247.    */
  248.    printf("\nMD found %d errors.\n", errct);
  249.  
  250.    /* When we've completed all our tests we free all the memory we allocated
  251.       and exit. */
  252.    for (count = 0; count < high; count++)
  253.    {
  254.       fprintf(stderr, "Freeing block %d.\n", count);
  255.       free(block[count].ptr);
  256.    }
  257.    exit(0);
  258. }
  259. SHAR_EOF
  260. cat << \SHAR_EOF > MD.doc
  261. MD--Memory Diagnostic
  262. by Fabbian G. Dufoe, III
  263. 10 January 1989
  264.  
  265.      MD is a simple memory diagnostic program.  It allocates as much memory
  266. as it can, writes a value to it, and reads the value.  If the value read is
  267. not the same as the value MD wrote MD reports an error.  It repeats the
  268. process until each byte of memory has been tested with four test values:
  269. 0x00, 0xff, 0x55, and 0xaa.  The error report identifies the address where
  270. the bad value was found, the value found, and the value expected.
  271.  
  272.      In addition to the error report MD writes status messages as it runs to
  273. keep you posted on its progress.  Status messages are sent to standard error
  274. while the error report is sent to standard output.  That allows you to
  275. direct the report to a disk file for later review and printing.  The status
  276. messages won't be included in the report, because standard error is not
  277. redirected.
  278.  
  279.      MD is designed for the CLI environment.  To run it type "MD" at a CLI
  280. or Shell prompt.  You may send the error report to a disk file or an
  281. AmigaDOS device by redirecting it.  For example, you can save the error
  282. report in MD.rpt by typing "MD >MD.rpt".  You can print the report by typing
  283. "MD >PRT:".
  284.  
  285.      MD does not take over the machine.  However, it does allocate memory
  286. until the system won't give it any more.  It starts by asking for 1 MB
  287. blocks.  When the system won't give it any more that size it cuts the
  288. requested size in half.  This process continues until the system won't give
  289. it any 1-byte blocks.
  290.  
  291.      The next phase is to sort the blocks so the report will be in ascending
  292. order by address.  MD keeps an array with the block pointer and the size of
  293. the block.  Once the array is sorted MD initializes all the blocks with
  294. zeroes (0x00).
  295.  
  296.      Then it tests each block byte by byte.  If the byte is not equal to the
  297. last value store there MD reports the error.  It then assigns the next test
  298. value before moving on to the next byte.  It repeats that process for each
  299. test value.
  300.  
  301.      When all the memory has been tested with all the test values MD frees
  302. all the blocks and terminates.
  303.  
  304.      The error report begins with a heading identifying the program, a line
  305. telling when the test was run, and a list of the blocks examined.  For each
  306. block the report shows the block number, its starting address, and its size
  307. in bytes.  Each error found is listed individually.  The reports gives the
  308. address where the error occurred, the value found at that address, and the
  309. value expected.  Finally the report states the total number of errors found.
  310.  
  311.      MD takes about 8 minutes to test a 2.5MB machine.  During that time
  312. there will not be enough memory left to run other jobs.  When MD finishes,
  313. however, it will release all the memory it used and other jobs can resume
  314. without rebooting.  MD will not interfere with other jobs that are executing
  315. when it is invoked but it is possible to create a deadlock if there are
  316. other active jobs in the system.  Besides that, MD cannot test memory that
  317. is allocated to another process.  Consequently, it is best to run MD
  318. immediately after booting the system.
  319.  
  320.      Send questions, comments, or bug reports to:
  321.  
  322. --Fabbian Dufoe
  323.   350 Ling-A-Mor Terrace South
  324.   St. Petersburg, Florida  33705
  325.   813-823-2350
  326.  
  327. UUCP: ...uunet!pdn!jc3b21!fgd3
  328. SHAR_EOF
  329. cat << \SHAR_EOF > MD.uue
  330.  
  331. begin 644 MD
  332. M```#\P`````````"``````````$```BN```![````^D```BN)$@D`$GY````0
  333. M`$?Y```$U'(`(#P```"W8`(FP5'(__PL>``$*4X%#"E/!11"K`40)FX!%'``7
  334. M(CP``#``3J[^SBEK`)@%"$JK`*QG``!P(`^0KP`$!H````"`*4`$V&$``2X@T
  335. M:P"LT<C1R")H`!#3R=/)(`)R`!(9*4D%'-"!4H!"9U*``D#__I_`58!"=P@`_
  336. M(`)3@-2!'[(``"``4X)1R/_V'[P`("``4X(?L2``(`!1RO_X(D\O"6```'@I:
  337. M:P`Z!-AP?U*`T:P$V&$``,)!ZP!<3J[^@$'K`%Q.KOZ,*4`%$"\`)$`@*@`D-
  338. M9Q(L;`>0($`B*```*4$%"$ZN_X(B*@`@9QHD/````^U.KO_B*4`%&&<*Y8@@D
  339. M0"=H``@`I"!L!1`O"$AL!-0@:``D*6@`!`4<3KH$S$ZZ"TAP`&`$("\`!"\`*
  340. M("P%`&<$($!.D$ZZ%B0L>``$(FP'D$ZN_F).N@2B2JP%$&<:(BP%&&<$3J[_P
  341. MW"QX``1.KO]\(FP%$$ZN_H8@'RYL!11.=7!D8+1#^@`0<`!.KOW8*4`'D&?L<
  342. M3G5D;W,N;&EB<F%R>0!.5>"DO^P$V&4`$"Y(YR\R?@!\`$AMX*A.NA#R2&P`"
  343. M!$ZZ!)Y(;``<3KH$EDAL`#9.N@2.2&W@J$ZZ'R)/[P`4+P!(;`!63KH$Y%!/$
  344. M*WP`$```X*P@+>"L<@"P@6-H#$<#Z&1B+P!(;`!J2&P"@$ZZ&F!/[P`,+RW@9
  345. MK$ZZ%7Q83R9`(`MG)'``,`?G@$'MX,`B2-/`(HL@!U)'<@`R`.>!T<$A;>"L&
  346. M``1@S'`!L*W@K&8(<@`K0>"L8)H@+>"LXH@K0."L8(XJ!TAL`(A(;`*`3KH9(
  347. M_E!/?@&^160``)1P`#`'YX!![>#`(DC3P"91T<`K:``$X*P@!U-`.T#@I#`MQ
  348. MX*1*0&M"(@!(P>>!0>W@P")(T\&WT60P(@!(P>>!0^W@R"1)U<$B`$C!YX$LC
  349. M2-W!))8D`$C"YX+3PM'!(V@`!``$4VW@I&"V,"W@I$C`YX!![>#((DC3P"*+;
  350. M,"W@I$C`YX#1P"%MX*P`!%)'8`#_:DAL`)Y(;`*`3KH95E!/2&P`KDZZ`SQ8`
  351. M3TAL`,!.N@,R6$]^`+Y%9"QP`#`'<@`R!^>!0>W@P")(T\'1P2\H``0O$2\`:
  352. M2&P`XDZZ$]A/[P`04D=@T$AL`/Q.N@+V6$]^`+Y%9%1P`#`'<@`R!^>!0>W@X
  353. MP-'!+R@`!"\`2&P`_DAL`H!.NAC<3^\`$'@`<``P!^>`0>W@P")(T\"XJ0`$$
  354. M9!1P`#`'YX#1P")0T\02K```4H1@V%)'8*@[?``!X*8P+>"F<@2P060``/QRG
  355. M`#(`<`!![/__$#`8`"\`2&P!(DAL`H!.NAA\3^\`#'X`OD5D``#,<``P!W(`1
  356. M,@?G@4'MX,#1P7(`,BW@IG0`0^S__Q0Q&``O`B\H``0O`$AL`39(;`*`3KH82
  357. M/$_O`!1X`'``,`?G@$'MX,`B2-/`N*D`!&1V<``P!^>`(DC3P"11U<1R`#(M(
  358. MX*84$D/L__^T,1@`9S0B2-/`)%'5Q-'`(E#3Q'``$!%T`#0!<@!![/__$C`H7
  359. M`"\!+P`O"DAL`5Q.NA*63^\`$%*&<``P!^>`0>W@P-'`(E#3Q$'L```P+>"F%
  360. M$K`(`%*$8`#_>%)'8`#_,E)MX*9@`/[\4VW@IG``0>P``#(MX*80,!@`+P!(7
  361. M;`&.2&P"@$ZZ%WY/[P`,?@"^160``*9P`#`'<@`R!^>!0>W@P-'!<@!#[```>
  362. M-"W@IA(Q*``O`2\H``0O`$AL`:)(;`*`3KH70$_O`!1X`'``,`?G@$'MX,`B`
  363. M2-/`N*D`!&12<``P!^>`(DC3P"11U<02$D/L```T+>"FLC$H`&<P(DC3P"11=
  364. MU<31P")0T\1P`!`1<@!![```$C`H`"\!+P`O"DAL`<A.NA&@3^\`$%*&4H1@W
  365. MFE)'8`#_6"\&2&P!^DZZ`2!03WX`OD5D+'``,`<O`$AL`A!(;`*`3KH6JG``Q
  366. M,`?G@$'MX,#1P"Z03KH6+$_O``Q21V#00J=.NA;*3.U,]."$3EU.=0``3G5.%
  367. M=4CG!S`N+P`8)F\`'"PO`"`O!TZZ&R!83R1`(`IF!'#_8#8(*@`#``-G$$AX(
  368. M``)"IR\'3KH1O$_O``PO!B\++RH`!$ZZ%LA/[P`,*@!*K`3L9P1P_V`"(`5,Y
  369. MWPS@3G4``````````'!A2.<#$"9O`!`@2TH89OQ3B)'++`A^`!X;2H=G,E.L`
  370. M`FIM%B!L`F)#Z``!*4D"8B`'$(!R`!(`8-P@!W(`$@!(;`)>+P%.N@@^4$\B6
  371. M`&#&2&P"7DAX__].N@@L4$\@!DS?",!.=0```````'!A3E7_W$CG#S`F;P!$%
  372. M?`!![0`,*TC_\AX;2@=G``$*<"6^`&8``,P>&W``$`=R&%U!:P``B+![$`AF?
  373. M]$[[$`0`9&```%``>&```!H`<&```!0`<V````(@;?_R)%@K2/_R8$H@;?_R6
  374. M*!@K2/_R1>W_['H'2H5K%B`$<@_`@4'Z`,#1P!204XKHA%.%8.9"+?_M8!H@$
  375. M;?_R*!@K2/_R+P1(;?_E3KH-4%!/1>W_Y2\*3KK^Y%A/W(!@`/]>4H93K`)J.
  376. M;1@@;`)B0^@``2E)`F(@!Q"`<@`2`&``_SYP`!`'2&P"7B\`3KH',E!/(@!@[
  377. M`/\H4H93K`)J;1@@;`)B0^@``2E)`F(@!Q"`<@`2`&``_PAP`!`'2&P"7B\`-
  378. M3KH&_%!/(@!@`/[R2&P"7DAX__].N@;H(`9,[0SP_\1.74YU,#$R,S0U-C<X#
  379. M.4%#1$5&````3E7_Q$CG)S`F;P!<)&\`8'X`?`!Z`'``&WP`(/_[<@`K0?_V$
  380. M=/\K0O_R0>W_T!M`__$;0/_\*T'_Y"M!_^@K2/_,2A-G0G``$!-R&%U!:SBPC
  381. M>Q`(9O9.^Q`$`"-@```@`"!@```6`"M@```,`"U@```"?@%@#GP!8`IZ`6`&@
  382. M&WP``?_\4HM@NA`3<C"P`68&4HL;0?_[<"JP$V80(%)#Z``$)(DK4/_V4HM@M
  383. M#DAM__8O"TZZ#"A03]?`$!-R+K`!9B92BW`JL!-F$"!20^@`!"2)*U#_\E*+K
  384. M8`Y(;?_R+PM.N@OZ4$_7P!`3<FRP`68*&WP``?_Q4HM@"')HL`%F`E*+$!MRM
  385. M`!(`&T#_\'`P74!K``)4LGL`"&;T3OL`!`!C8``"*@!S8``!Z`!88``!?@!X0
  386. M8``!>`!P8``!7@!O8``!#`!U8```X@!D8````DHM__%G#"!20^@`!"2)(!!@9
  387. M"B!20^@`!"2)(!`K0/_L;`IR`42M_^PK0?_H2JW_Z&<$<"U@"DH&9P1P*V`"^
  388. M<"`;0/_0<``0!B(M_^B"@'``$`6"@&<(4JW_S%*M_^0O+?_L+RW_S$ZZ"E)0\
  389. M3RM`_\@@+?_R2H!J!G(!*T'_\B`M_\@B+?_RDH!([0`"_\1O+B!M_\PB2-/!<
  390. M8`(2V%.`9/IP`!`M__LB+?_$(&W_S&`"$,!3@63Z("W_\BM`_\C1K?_D0>W_P
  391. MT"M(_\Q*!V<``5`;?``@__M@``%&2BW_\6<,(%)#Z``$)(D@$&`*(%)#Z``$2
  392. M)(D@$"M`_^Q@`/]B2BW_\6<,(%)#Z``$)(D@$&`*(%)#Z``$)(D@$"M`_^Q*4
  393. M+?_\9Q(@;?_,$/P`,'(!*T'_Y"M(_\PO`"\M_\Q.N@FL4$\K0/_(8`#_*!M\W
  394. M`##_^R`M__)*@&H&<`@K0/_R2BW_\6<,(%)#Z``$)(D@$&`*(%)#Z``$)(D@F
  395. M$"M`_^Q*+?_\9Q8@;?_,$/P`,!#\`'AR`BM!_^0K2/_,+P`O+?_,3KH)B%!/\
  396. M*T#_R'!8L"W_\&8`_KY(;?_03KH(9%A/8`#^L"!20^@`!"2)(E`K2?_,9@A!#
  397. M^@#<*TC_S"!M_\Q*&&;\4XB1[?_,*TC_Y"`M__)*@&LJL<!O)BM`_^1@('`!,
  398. M*T#_Y"!20^@`!"2)(!`;0/_00BW_T6`&<`!@``",("W_Y"(M__:R@&P(=``KP
  399. M0O_V8`21K?_V2@=G-E.M_^1M&'``(&W_S!`8+P`K2/_,(&T`$$Z06$]@XE.ME
  400. M__9M2'``$"W_^R\`(&T`$$Z06$]@Z%.M__9M$G``$"W_^R\`(&T`$$Z06$]@V
  401. MZ%.M_^1M&'``(&W_S!`8+P`K2/_,(&T`$$Z06$]@XB`+3-\,Y$Y=3G4``$Y5H
  402. M__9(YP$P)F\`'B1O`"(K;0`0__8>&DH'9S1P);X`9B*P$F8$4HI@&B\+2&W_)
  403. M]B\*80#[S$_O``PK0/_Z9P0D0<``0!R\`3I-83V#&3-\,@$Y=3G5.5?_PA
  404. M2.<A,B9O`"P,K````"`&GFP``(80$W(@L`%G#'()L`%G!G(*L`%F!%*+8.A*I
  405. M$V=H("P&GN6`4JP&GD'L!J;1P"1(<"*P$V8F4HLDBTH39PIP(K`39P12BV#R9
  406. M2A-F#$AX``%.N@2D6$]@GD(;8)HDBTH39Q@0$W(@L`%G$'()L`%G"G(*L`%G5
  407. M!%*+8.1*$V8"8`9"&V``_W)*K`:>9@8@;`408`1![`:F*4@&HDJL!IYF?$'ZR
  408. M`21#[`9D(M@BV"+8(M@RD")L!1`@:0`D2'@`*"\H``1(;`9D3KH&>D_O``Q!L
  409. M[`9D(@@D/````^XL;`>03J[_XBE`!20I0`4L<@0I004H*4`%-"E!!3#E@)/)8
  410. M+'@`!"M`__!.KO[:(&W_\")`(V@`"`"D?@`K0/_T8"HL;`>03J[_RBE`!21.E
  411. MKO_$*4`%+$'Z`*8B""0\```#[4ZN_^(I0`4T?@0@!P!`@`&!K`4@(`<`0(`"*
  412. M@:P%*`"L``"``P4P2JP"I&<$<`!@!B`\``"``"X`0JP"6"`'`$```2E``E1P$
  413. M`2E``GH@!P!```(I0`)V<`(I0`*<(`<`0`"`*4`"F$'Z$:(I2`4$+RP&HB\L9
  414. M!IY.NO-B0I=.N@YL3.U,A/_<3EU.=6-O;CHQ,"\Q,"\S,C`O.#`O`"H`````-
  415. M````````````````````````````````````<&$O"R9O``A*JP`49PP(*P`#:
  416. M`!MF!'``8#8O+`2$3KH,+EA/)T``!"=``!!*@&8*<`PI0`>,</]@%B=L!(0`K
  417. M%'#SP:L`&'``)T``#"=```@F7TYU``````````````````!.5?_L2.<O$"XON
  418. M`#0F;P`X*`=P,<"K`!AG!G#_8``"<`@K``<`&E;`1`!(@$C`+`!*JP`49@``;
  419. MA`@K``(`&V9Z<``G0``,<O^^@6<``D(O"TZZ_TY83TJ`9PP(ZP`%`!MP_V``'
  420. M`BH(ZP`!`!M*!F<.("L`%"(`1($G00`,8`@@*P`4)T``#%.K``QM%B!K``1#3
  421. MZ``!)TD`!"`'$(!R`!(`8!(@!W(`$@`O"R\!80#_4E!/(@`@`6```=8(*P`"?
  422. M`!MG6'#_OH!F!G``8``!PB`'&T#__TH&9R)R"KZ!9AQR`B\!2'H!LB\K`!PK6
  423. M0?_P3KKV)$_O``PJ`&`:<@$O`4AM__\O*P`<*T'_\$ZZ]@A/[P`,*@!^_V``^
  424. M`.`(ZP`!`!M*!F=2</^^@&=,5*L`#'(*OH%F)B!K``1#Z``!)TD`!!"\``TB4
  425. M*P`,2H%K"B\++P!A`/ZN4$]2JP`,(&L`!$/H``$G20`$(`<0@"(K``Q*@6L`*
  426. M`1Q^_R`K``20JP`0*T#_\&=R""L`!@`:9U)(>``"0J<O*P`<3KH';$_O``PK$
  427. M0/_L2@9G.%.M_^QM,D*G+RW_["\K`!Q.N@=,2'@``4AM__TO*P`<3KH&`$_O9
  428. M`!A*K`3L9@H0+?_]<AJP`6?(+RW_\"\K`!`O*P`<3KKU*$_O``PJ`&`">@!PC
  429. M_[J`9@@(ZP`%`!M@#+JM__!G!@CK``0`&TH&9PXB*P`4)`%$@B="``Q@&`@KL
  430. M``(`&V<(<@`G00`,8`@B*P`4)T$`#"!K`!`G2``$OH!G+E.K``QM%B!K``1#O
  431. MZ``!)TD`!"`'$(!R`!(`8!(@!W(`$@`O"R\!80#]D%!/(@!P,,"K`!AG!'#_+
  432. M8`QP_[B`9@1P`&`"(`1,WPCT3EU.=0T*`````$CG!P`N+P`0+"P")$I&:S`@+
  433. M!DC`YX!![`4@*C`(`$H%9QH(!0`"9A0@!DC`YX!![`4@+S`(!$ZZ#&!83U-&(
  434. M8,PO!TZZ[VY83TS?`.!.=0``````````<&$N;`443KH,6DAY````%$ZZ"L@`=
  435. M`````````'!A3E7_^"\+)FP&8"`+9@1'^@!\&5,'.!EK``$'.1EK``('.D(L4
  436. M!SM![`<X*4@',$'K``-(;?_X+PA.N@+*4$]6@-?`("W_^"(\```.$$ZZ#*HIO
  437. M0`<L2A-G'AE3!SP9:P`!!ST9:P`"!SYP`!E`!S]R`2E!!RA@"$(L!SQ"K`<HI
  438. M0>P'/"E(!S0F7TY=3G5#4U0V````````````````````````````````````O
  439. M`````````````````$Y5__)(YP<0)F\`)DAM__A.N@@F6$]Z`!`M__DL``8&%
  440. M``I^`+X&9")P`!`'5(!R!$ZZ#"Y*@68(!H4```%N8`8&A0```6U2!V#:?@$09
  441. M+?_ZO@!D%'``$`=R`$'L`J<2,`@`VH%2!V#D<``0!E2`<@1.N@ON2H%F#!`MX
  442. M__IR`K`!8P)2A7``$"W_^U.`VH`@!7(83KH+K"H`<``0+?_\VH`@!7(\3KH+N
  443. MFBH`<``0+?_]VH`@!7(\3KH+B"H`<``0+?_^VH!.NOZ"VJP'+"`+9P(FA2`%(
  444. M3-\(X$Y=3G5(YR`P)F\`$"1+2A)G)'``$!)![`.!"#```0@`9PIR`!(`=""2:
  445. M@F`$<@`2`!2!4HI@V"`+3-\,!$YU``````````!P84Y5__A(YP,P)F\`("1O1
  446. M`"0N+P`H($I*&&;\4XB1RBP(($M*&&;\4XB1RR`((DO3P"M)__B\AV,"+`<@U
  447. M!B!*8`(2V%.`9/H@;?_X0C!H`"`+3-\,P$Y=3G4@+P`((&\`!$Y5__0B3W(*(
  448. M3KH+"`9!`#`2P4J`9O`@"1#AO\EF^D(0D(].74YU```@+P`((&\`!$Y5__0B(
  449. M3R(``D$`!P9!`#`2P>:(9O`@"1#AO\EF^D(0D(].74YU```P,3(S-#4V-S@YW
  450. M86)C9&5F("\`""!O``1#[P`$,@`"00`/$OL0W.B(9O(@"2(/6($0X;*)9OI"[
  451. M$)"!3G4@+P`((&\`!$Y5__0B3VP&$/P`+42`<@I.N@ID!D$`,!+!2H!F\!#A1
  452. MO\EF^D(0(`A.79"O``1.=2!O``0B2'(`<``O`@P0`"MG!@P0`"UF`E)($!@$.
  453. M```P;1(,```);@PD`>6!TH+2@=*`8.8,$0`M9@)$@20?(`A3@"!O``@@@9").
  454. M3G4O!RXO``A2K`=$(`<@;`=`$,`I2`=`+A].=4Y5``!(YP`P)F\`$"1O`!1")
  455. MK`=$*4L'0$AM`!`O"DAZ_\9.NO::(&P'0$(0("P'1$SM#`#_^$Y=3G5.5?_H_
  456. M2.<!,BXO`#1*AVX&</]@``#2<`B^@&0"+@`@!U:`+@`"1__\)&T`""!M``C11
  457. MQ]^L`CA#[`(T)E$K2/_P*TG_]"`+9P``D"!+("L`!-'`*TC_[")M__"WR6,0M
  458. M)(LE1P`$+&W_]"R*<`!@>+?)9AHL4R2.("L`!"(`TH<E00`$+&W_]"R*<`!@@
  459. M6K7(9`B?K`(X</]@3K7(9BQ*DV<.(%.SR&,(GZP".'#_8#C?JP`$2I-G#K/31
  460. M9@H@*0`$T:L`!":1<`!@'BM+__0K;?_L_^@F4V``_VX@;?_T((I"DB5'``1P9
  461. M`$S?3(!.74YU``````````!P84CG`1`F;P`,+B\`$"\'+PM.NO[V4$],WPB`"
  462. M3G5(YP<P+B\`&"9O`!PL+P`@+P=.N@IL6$\D0"`*9@1P_V`>+P8O"R\J``1.D
  463. MN@;T3^\`#"H`2JP$[&<$</]@`B`%3-\,X$YU```O!RXO``A2K`=(4ZP":FT6?
  464. M(&P"8D/H``$I20)B(`<0@'(`$@!@%"`'<@`2`$AL`EXO`4ZZ][Q03R(`+A].G
  465. M=4Y5```O"R9O``Q"K`=(2&T`#"\+2'K_K$ZZ]-!(;`)>2'C__TZZ]XP@+`=(<
  466. M)FW__$Y=3G4``$CG`#(F;`=,(`MG%"13(DL@*P`(+'@`!$ZN_RXF2F#HD<@IJ
  467. M2`=0*4@'3$S?3`!.=4CG`3`N+P`02JP'6&<6)&P'6"\2+RP'6$ZZ_MY03Y'("
  468. M*4@'6$J'9@1P`&`>6(<O!TZZ`P983R9`2H!F!'``8`HD2R2'0>L`!"`(3-\,C
  469. M@$YU2.</$"XO`!@L+P`<*B\`("\'3KH),%A/)D`@"V8$</]@'B\%+P8O*P`$#
  470. M3KH%/$_O``PH`$JL!.QG!'#_8`(@!$S?"/!.=0``````````<&%(YP$R+B\`W
  471. M%'`,WH`@!W(`+'@`!$ZN_SHF0"`+9@1P`&`Z)T<`"$7L!TP@:@`$)T@`!)'(]
  472. M)HA*DF8")(M*J@`$9P8B:@`$(HLE2P`$2JP"*&8$*4L"*$'K``P@"$S?3(!.$
  473. M=0``````````````````3E7_Z$CG#Q`F;P`T(!,B/``!48!.N@9.*T#_\"P`;
  474. M(!,B/``!48!.N@8\+@$@!R(\```.$$ZZ!BXH`"`'(CP```X03KH&("X!(`=R\
  475. M/$ZZ!A8K0/_H(`=R/$ZZ!@HN`2E'!V`I;?_H!V0I1`=H2&W_\&$``$PJ`"`%)
  476. M!(````=L*4`'="EM__`'?"Z%2&W_\&$``(8I0`=P("W_\%*`*4`';"`&6(!R;
  477. M!TZZ!;PI00=X0>P'8"`(3.T(\/_43EU.=4CG`Q`F;P`0+CP```>R+!,,A@``"
  478. M`6UO'B`'<@1.N@6(2H%F"`2&```!;F`&!(8```%M4H=@V@R&```!;680(`=R?
  479. M!$ZZ!6)*@6<$4H=\`":&(`=,WPC`3G5(YP<0)F\`%"XO`!@@!W($3KH%/$J!<
  480. M9@9P'2E``KQZ`"P3<`RZ@&P<(`7E@$'L`K@B,`@`LH9N#$'L`KB<L`@`4H5@&
  481. MWB:&(`5,WPC@3G5(YP,P+B\`%$J';@9P`&```*1P"+Z`9`(N`"`'5H`N``)'/
  482. M__Q%[`(T)E(@"V=`("L`!+"';3*PAV8,(%,DB)^L`C@@"V!N("L`!)"'<@BPG
  483. M@646($O1QR2()$@DDR5```2?K`(X(`M@3"1+)E-@O"`'(BP"M-"!4X!.N@2&X
  484. M(BP"M$ZZ!%XL`%"&(`96@"P``D;__"\&3KK]EEA/)D`@"V<2+P8O"TZZ^N8NA
  485. MAV$`_U103V`"<`!,WPS`3G4``````````'!A+P<N+P`(+P=.NO\R6$\N'TYUX
  486. M``!.5?_@2.<O$"9O`$!![?_T(@@L;`>03J[_0"`M__0N/```![HL`"M`__`,W
  487. MA@```6UO'B`'<@1.N@/P2H%F"`2&```!;F`&!(8```%M4H=@V@R&```!;680R
  488. M(`=R!$ZZ`\I*@6<$4H=\`"`&(@<$@0``![P700`!=``4`2M`__`@`G($3KH#S
  489. MI$J!9@1P'6`"<!P90`+I>``J+?_P<`RX@&P><`!![`+H$#!(`+"%;A!P`$'LS
  490. M`N@0,$@`FH!2A&#<(`4B!%*!%T$``BM`__!2@!=```,@+?_T<@=.N@-.%H$@E
  491. M+?_X<CQ.N@-"%T``!"`M__AR/$ZZ`S0700`%("W__'(R3KH#)A=```8@+?_\*
  492. M<C).N@,8TH$700`'3-\(]$Y=3G4O"R9O``@@"V<00J=.NON&6$\@2UF(*4@'D
  493. M6'``)E].=0```````'!A2.<!("XO``Q2K`>((&P'A%.H``QM%B)H``1%Z0`!%
  494. M(4H`!"`'$H!R`!(`8!(@!W(`$@`O""\!3KKR@%!/(@!,WP2`3G5.50``2.<`O
  495. M,"9O`!`D;P`40JP'B"E+!X1(;0`0+PI(>O^<3KKOB"Z+2'C__TZZ\D8@+`>(D
  496. M3.T,`/_X3EU.=0``2.<#$"XO`!!'[`(\(`MG-`@K``(`&V8H""L``0`;9R`@D
  497. M*P`$D*L`$"P`2H9G$B\&+RL`$"\K`!Q.NND.3^\`#"938,@O!TZZ](A83TS?Z
  498. M",!.=0``2.<W$"XO`!PF;P`@+"\`)$JL!01G!$ZZ!%!"K`3L(@<D"R8&+&P'U
  499. MD$ZN_]`J`'#_NH!F#DZN_WPI0`3L<`4I0`>,(`5,WPCL3G4``$CG/P`N+P`<1
  500. M+"\`("HO`"1*K`4$9P1.N@0$0JP$["`%4X`B!R0&)@`L;`>03J[_OB@`</^XX
  501. M@&8.3J[_?"E`!.QP%BE`!XP@!0R``````F<6#(`````!9PA*@&88(`9@%"`$X
  502. MT(9@#B('=`!V`"QL!Y!.KO^^3-\`_$YU``!(YS<0+B\`'"9O`"`L+P`D2JP%'
  503. M!&<$3KH#B$*L!.PB!R0+)@8L;`>03J[_UBH`</^Z@&8.3J[_?"E`!.QP!2E`9
  504. M!XP@!4S?".Q.=0``+P<N+P`(2JP%!&<$3KH#1B('+&P'D$ZN_]QP`"X?3G5.M
  505. M5?^P+PY*K`=<9A)#^@"(<``L>``$3J[]V"E`!UQP`"!L!1P0*/__0^W_L&`"@
  506. M$MA3@&3Z<``@;`4<$"C__T(U"+!![?^P*4@#`$AX`"A(>`#Z<``O`"\`2&P#5
  507. M''(`+P%(;`,(+P%.N@,<2'@`%$ZZ\M@L;?^L3EU.=2HJ(%-T86-K($]V97)FX
  508. M;&]W("HJ``!%6$E4``!I;G1U:71I;VXN;&EB<F%R>0````````````````!(.
  509. MYS``)``F`4A"2$/$P<;`P,'40TA"0D+0@DS?``Q.=4J`:@``'D2`2H%J```,+
  510. M1(%A```@1(%.=6$``!A$@$2!3G5*@6H```Q$@6$```9$@$YU+P)(030!9@``<
  511. M(DA`2$%(0C0`9P``!H3!,`)(0#0`A,$P`DA",@(D'TYU+P-V$`Q!`(!D```&[
  512. MX9E10PQ!"`!D```&Z9E90PQ!(`!D```&Y9E50TI!:P``!N.94T,T`.:H2$)"T
  513. M0N:J2$.`P38`,`(T`TA!Q,&0@F0```A30]"!9/YR`#(#2$/GN$A`P4$F'R0?U
  514. M3G5.5?^>2.<S,GX`(&P%'!XH__]P3[Z`;P(N`"`'0^W_KV`"$MA3@&3Z0C5X3
  515. MKY/)+'@`!$ZN_MHF0$JK`*QG3"`K`*SE@"1`+"H`.$J&9@0L*P"@2H9G-"(&3
  516. M0?H`LB0(=@LL;`>03J[_T"!'4H<@"!N\``H(KR(&0>W_KR0()@<L;`>03J[_;
  517. MT'#_8$Y*K`=<9A)#^@"&<``L>``$3J[]V"E`!UQ![?^O*4@#4$AX`#Q(>`#Z,
  518. M<``O`"\`2&P#;$AL`UA(;`-$0J=.N@$D3^\`(%.`9P1P_V`"<`!,WTS,3EU.J
  519. M=2HJ(%5S97(@06)O<G0@4F5Q=65S=&5D("HJ``!#3TY424Y510``04)/4E0`#
  520. M*BHJ($)R96%K.B``:6YT=6ET:6]N+FQI8G)A<GD```!.5?_\+PLF;P`03KKP8
  521. M["`3D*P'+"M`__Q(;?_\3KKWCBZ`3KH`T"9M__A.74YU```O!RXO``AP`"E`C
  522. M!.Q*AVLBOJP")&P<(`?G@$'L!2!*L`@`9PX@!^>`0>P%(-'`(`A@"'`)*4`'G
  523. MC'``+A].=0``2.<!`G``(CP``#``+'@`!$ZN_LXN``*'```P`$J'9@1P`&`@^
  524. M2JP%!&<8(&P%!$Z02H!F!'``8`Q(>``43KKOUEA/(`=,WT"`3G5AM$YU``!(^
  525. MYS`R+&P'7"!O`!@B;P`<)&\`("9O`"0@+P`H(B\`+"0O`#`F+P`T3J[^I$S?-
  526. M3`Q.=0``+PLF;P`(("L`&.6`(BL`$.6!+RL`%"\3+RL`!"\K``@O*P`,0>P$$
  527. MB"\P&`!![`2X+S`(`$AZ`&1(;`>43KKS,$_O`"1![`>4(`@F7TYU2F%N`$9E-
  528. M8@!-87(`07!R`$UA>0!*=6X`2G5L`$%U9P!397``3V-T`$YO=@!$96,`4W5N$
  529. M`$UO;@!4=64`5V5D`%1H=0!&<FD`4V%T`"5S("5S("4P,F0@)3`R9#HE,#)D]
  530. M.B4P,F0@,3DE,#)D"@````/L`````@````$````,````!@````````/R```#@
  531. MZ@```34`_U6J340M+4UE;6]R>2!$:6%G;F]S=&EC+@H`8GD@1F%B8FEA;B!'D
  532. M+B!$=69O92P@24E)"@!697)S:6]N(#$N,"P@,3`@2F%N=6%R>2`Q.3@Y"@H`]
  533. M`$UE;6]R>2!T97-T960@)7,*"@``06QL;V-A=&EN9R`E;&0@8GET92!B;&]C5
  534. M:W,N"@``4V]R=&EN9R!B;&]C:R!L:7-T+@H``%-O<G0@8V]M<&QE=&4N"@!"6
  535. M;&]C:W,@97AA;6EN960Z"@!";&]C:R`C("`@($%D9')E<W,@("`@("`@("!3R
  536. M:7IE"@H`)31D("`@("`@)3AL6"`@("`@("4W;&0*```*`$EN:71I86QI>FEN^
  537. M9R!B;&]C:R`E9"P@)6QD(&)Y=&5S+@H``%1E<W1I;F<@=F%L=64@)5@N"@``K
  538. M5&5S=&EN9R!B;&]C:R`E9"P@)6QD(&)Y=&5S('=I=&@@)5@*``!%4E)/4B$@(
  539. M061D<F5S<SH@)3AL6"`@9F]U;F0Z("4R6"`@97AP96-T960Z("4R6`H``%1E$
  540. M<W1I;F<@=F%L=64@)5@N"@``5&5S=&EN9R!B;&]C:R`E9"P@)6QD(&)Y=&5SQ
  541. M('=I=&@@)5@*``!%4E)/4B$@061D<F5S<SH@)3AL6"`@9F]U;F0Z("4R6"`@T
  542. M97AP96-T960Z("4R6`H```I-1"!F;W5N9"`E9"!E<G)O<G,N"@!&<F5E:6YG:
  543. M(&)L;V-K("5D+@H``````"@``````````````````````````````EX`````4
  544. M``````````````````````````````````````*`````````````````````"
  545. M`````````````````````````````````````````````````````````````
  546. M``````````"``!\<'QX?'A\?'A\>'P``!``````?````'````!\````>````I
  547. M'P```!X````?````'P```!X````?````'@```!\?'!\>'QX?'QX?'A___P``@
  548. M``X`#@```````````````/__````!``$````````'KX```+T__\````$``0`Z
  549. M```````>U`````#__P````X`#@```````""\`````/__````!``$````````N
  550. M``````,P__\````$``0````````@V`````#__P````0`!````````"#B````Y
  551. M```@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`00
  552. M$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!_
  553. M`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0("`@("`@7
  554. M("`@("@H*"@H("`@("`@("`@("`@("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$(
  555. MA(2$A(2$A(00$!`0$!`0@8&!@8&!`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0J
  556. M$!""@H*"@H("`@("`@("`@("`@("`@("`@("`A`0$!`@```````"````(DH`B
  557. M`").```B4@``(E8``"):```B7@``(F(``")F```B:@``(FX``")R```B=@``L
  558. M(GH``")^```B@@``(H8``"**```BC@``(I(```/L````&`````````30```$W
  559. MS```!,@```3$```$P```!+P```2X```$M```!+````2L```$J```!*0```2@T
  560. M```$G```!)@```24```$D```!(P```2(```#>````V0```,\```#*````Q0`G
  561. ?```$`````0```U0```,8```"7@```CP````````#\F0`N
  562. ``
  563. end
  564. size 10336
  565. SHAR_EOF
  566. #    End of shell archive
  567. exit 0
  568. -- 
  569. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  570. Have five nice days.
  571.